package service

import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"log"
	"math/rand"
	"net/http"
	"net/url"
	constant "rongyy/src/constants"
	"rongyy/src/helper"
	"rongyy/src/middlewares"
	"rongyy/src/models"
	"strconv"
	"time"
)

type YktService struct {
	d *models.YktModel
}

func (ds *YktService) SaveYktData(req *models.ReqYiKaTongParams) (*models.YktModel, error) {
	sm := &models.YktModel{
		PayOrderId: req.PayOrderId,
		MchOrderId: req.MchOrderId,
		CardNo:     req.CardNo,
		IsUsed:     0,
	}
	data, err := sm.Insert()
	if err != nil {
		return nil, err
	}
	return data, nil
}

func (ds *YktService) Use(req *models.ReqYiKaTongParams) (*models.YktModel, error) {
	sm := &models.YktModel{
		PayOrderId: req.PayOrderId,
		MchOrderId: req.MchOrderId,
		CardNo:     req.CardNo,
		IsUsed:     1,
	}
	data, err := sm.Used()
	if err != nil {
		return nil, err
	}
	return data, nil
}

func (ds *YktService) Query(req *models.ReqYiKaTongParams) ([]models.YktModel, int64, error) {
	sm := &models.YktModel{
		PayOrderId: req.PayOrderId,
		MchOrderId: req.MchOrderId,
		CardNo:     req.CardNo,
	}
	data, total, err := sm.Query(req.CardNo)
	if err != nil {
		return nil, 0, err
	}
	return data, total, nil
}

// Query
//
//	@Description: 下单
//	@receiver ds
//	@param req
//	@return []models.YktModel
//	@return int64
//	@return error
func (ds *YktService) Pay(code string, reqPay *models.YktPayApiReqModel) (*models.YktPayFinalPayUrlResp, error) {
	data, has, err := (&models.CardModel{}).GetPatientBySourceId(reqPay.PatientId)
	if !has {
		return nil, fmt.Errorf("用户信息不存在，请先建卡")
	}
	MchOrderId := "CDGWYKT" + strconv.FormatInt(time.Now().Unix(), 10) + reqPay.PatientId

	order, has, err := (&models.RegisterModel{}).FindByTransactionId(reqPay.TransactionId)
	if !has {
		return nil, errors.New("订单不存在")
	}
	//// 查看订单是否超时
	current := time.Now().Format("2006-01-02 15:04:05")
	currentT, err := time.Parse("2006-01-02 15:04:05", current)
	if err != nil {

	}
	regTime, _ := time.Parse("2006-01-02 15:04:05", order.CreatedAt.String())
	if (currentT.Unix() - regTime.Unix()) > 610 {
		return nil, errors.New("订单已超时，请重新挂号")
	}

	if order.Status != "locked" || order.PayStatus != "" {
		return nil, errors.New("订单状态错误")
	}
	fee, err := helper.Str2int(order.Fee)
	if err != nil {
		return nil, errors.New("订单金额转换错误")
	}
	reqYkt := &models.YktPayReqModel{
		IdNameOrder:     data.RealName,
		IdNumberOrder:   data.IdNo,
		IdTypeOrder:     "01",
		MchOrderId:      MchOrderId,
		NotifyUrl:       reqPay.NotifyUrl,
		OrderAmount:     float64(fee) * 100,
		OrderCreateTime: time.Now().Format("2006-01-02 15:04:05"),
		OrderDesc:       reqPay.OrderDesc,
		OrderTitle:      reqPay.OrderTitle,
		OrderType:       "10001",
		PayType:         "1",
		WayCode:         "SBK",
	}
	middlewares.Logger.Println("一卡通支付 入参================", reqYkt)
	jsonData, err := json.Marshal(reqYkt)
	middlewares.Logger.Println("一卡通支付 入参================", string(jsonData))
	body, err := ds.invoke(string(jsonData), code)
	if err != nil {
		return nil, err
	}
	resps := &models.YktRespModel{}
	err = json.Unmarshal(body, resps)
	middlewares.Logger.Println("一卡通支付 出参1================", string(body))
	bizData := resps.BizData
	reqSm4De := &models.YktSm4DecryptoReq{
		Key:            constant.YKTDataSecret,
		EncryptContent: bizData.Data,
	}
	decryptData, err := helper.YktSm2Decrypto(reqSm4De)
	yktPayDeResp := &models.YktPayFinalResp{}
	err = json.Unmarshal([]byte(decryptData), yktPayDeResp)
	middlewares.Logger.Println("一卡通支付 出参2================", yktPayDeResp)
	yktPayFinalPayUrlResp := &models.YktPayFinalPayUrlResp{}
	err = json.Unmarshal([]byte(yktPayDeResp.PayUrl), yktPayFinalPayUrlResp)
	middlewares.Logger.Println("一卡通支付 出参3================", yktPayFinalPayUrlResp)
	// 入库
	reqOrderIn := &models.YktOrdersModel{
		IdNameOrder:   data.RealName,
		PatientId:     reqPay.PatientId,
		MchOrderId:    MchOrderId,
		TransactionId: reqPay.TransactionId,
		OrderAmount:   float64(reqPay.OrderAmount) * 100,
		//IdNumberOrder: reqPay.IdNumberOrder,
		PayOrderId: yktPayDeResp.PayOrderId,
		PayNo:      yktPayFinalPayUrlResp.ExtraData.PayNo,
	}
	_, err = reqOrderIn.Insert()

	reqPaying := &models.RegisterModel{
		OrderSn:       MchOrderId,
		PayStatus:     "paying",
		TransactionId: reqPay.TransactionId,
		PayWay:        "ykt",
	}
	err = (&RegistrationService{}).ChangeRegOrderPaying(reqPaying)
	if err != nil {
		middlewares.Logger.Println("ChangeRegOrderPaying - 错误", err)
	}
	// 该变订单状态
	// 下单成功，开始轮训订单查询接口
	if yktPayFinalPayUrlResp.ExtraData.PayNo != "" {
		var timer *time.Timer
		go func() {
			i := 0
			for {
				if i > 60 {
					timer.Stop()
					break
				}
				req := &models.YktQueryOrderReqModel{
					MchOrderId: yktPayDeResp.MchOrderId,
					PayOrderId: yktPayDeResp.PayOrderId,
				}
				jsonData1, _ := json.Marshal(req)
				data, err := ds.QueryOrder(string(jsonData1), "88800100001")
				if err != nil {
					fmt.Println("QueryOrder===========", err)
				}
				// 如果查询到，就确认支付
				if err == nil && data.PayStatus == "2" {
					reg, has, err := (&models.RegisterModel{}).FindByTransactionId(reqPay.TransactionId)
					if !has {
						fmt.Println("QueryOrder===========", err)
					}
					if err != nil {
					}
					local, _ := time.LoadLocation("Asia/Shanghai")
					date := time.Now().In(local).Format("2006-01-02")
					t := time.Now().In(local).Format("15:04:05")
					ConfirmRegReq := &models.Req1101Params{
						TransactionId:    reqPay.TransactionId,
						ScheduleItemCode: reg.ScheduleItemCode,
						PatientID:        reg.PatientId,
						PayModeCode:      "WXYKTZF",
						PayFee:           reg.Fee,
						QueueNo:          "",
						PayAmt:           reg.Fee,
						PlatformNo:       yktPayDeResp.MchOrderId,
						OutPayNo:         yktPayDeResp.PayOrderId,
						PayChannel:       "",
						POSPayStr:        "",
						PayDate:          date,
						PayTime:          t,
						UpdateBy:         "ykt_active",
						AppOrderCode:     "",
					}
					middlewares.Logger.Println("ykt Register - 入参1================", ConfirmRegReq)
					jsonData, err := json.Marshal(ConfirmRegReq)
					middlewares.Logger.Println("ykt Register - 入参2================", string(jsonData))

					ree, err := (&RegistrationService{}).Register(ConfirmRegReq)
					if err != nil {
						middlewares.Logger.Println("ykt Register - 错误", err)
					}
					middlewares.Logger.Println("ykt Register - 错误", ree)
					timer.Stop()
				}
				i++
				timer = time.NewTimer(4 * time.Second)
				<-timer.C
			}
		}()

	}
	return yktPayFinalPayUrlResp, err
}

// Query
//
//	@Description: 下单
//	@receiver ds
//	@param req
//	@return []models.YktModel
//	@return int64
//	@return error
func (ds *YktService) QueryOrder(jsonData string, code string) (*models.YktQueryOrderData, error) {
	//uri := "http://110.185.163.36:8003/engine/rest/"
	fmt.Println("====", string(jsonData))
	body, err := ds.invoke(jsonData, code)
	fmt.Println("====", string(body))
	if err != nil {
		return nil, err
	}
	resps := &models.YktRespModel{}
	err = json.Unmarshal(body, resps)
	bizData := resps.BizData
	if resps.BizData.Success {
		reqSm4De := &models.YktSm4DecryptoReq{
			Key:            constant.YKTDataSecret,
			EncryptContent: bizData.Data,
		}
		decryptData, err := helper.YktSm2Decrypto(reqSm4De)
		fmt.Println(decryptData)
		yktPayDeResp := &models.YktQueryOrderData{}

		err = json.Unmarshal([]byte(decryptData), yktPayDeResp)

		return yktPayDeResp, err
	}
	return nil, fmt.Errorf(resps.BizData.Message)
}

// 退费
func (ds *YktService) Refund(jsonData string, code string) (*models.YktRefundResp, error) {
	body, err := ds.invoke(jsonData, code)
	if err != nil {
		return nil, err
	}
	resps := &models.YktRespModel{}
	err = json.Unmarshal(body, resps)
	bizData := resps.BizData
	if resps.BizData.Success {
		reqSm4De := &models.YktSm4DecryptoReq{
			Key:            constant.YKTDataSecret,
			EncryptContent: bizData.Data,
		}
		decryptData, err := helper.YktSm2Decrypto(reqSm4De)
		fmt.Println(decryptData)
		yktPayDeResp := &models.YktRefundResp{}

		err = json.Unmarshal([]byte(decryptData), yktPayDeResp)
		return yktPayDeResp, err
	}
	return nil, fmt.Errorf(resps.BizData.Message)
}

func (ds *YktService) invoke(jsonData string, code string) ([]byte, error) {
	//uri := "http://110.185.163.36:8003/engine/rest/"
	appid := "A1000001317"           //应用APPID 医院需要替换
	dataSecret := "TfTvdFXsHzDABsRE" //data数据加密参数(密钥dataSecret生产服务后替换新的)
	//keystore := "MIICSwIBADCB7AYHKoZIzj0CATCB4AIBATAsBgcqhkjOPQEBAiEA/////v////////////////////8AAAAA//////////8wRAQg/////v////////////////////8AAAAA//////////wEICjp+p6dn140TVqeS89lCafzl4n1FauPkt28vUFNlA6TBEEEMsSuLB8ZgRlfmQRGajnJlI/jC7/yZgvhcVpFiTNMdMe8Nzai9PZ3nFm9zuNraSFT0KmHfMYqR0AC3zLlITnwoAIhAP////7///////////////9yA99rIcYFK1O79Ak51UEjAgEBBIIBVTCCAVECAQEEIMBUo7P3WCxoIJQoAoCtn+ZT2WdpGkEgP+nWnd1m1+z1oIHjMIHgAgEBMCwGByqGSM49AQECIQD////+/////////////////////wAAAAD//////////zBEBCD////+/////////////////////wAAAAD//////////AQgKOn6np2fXjRNWp5Lz2UJp/OXifUVq4+S3by9QU2UDpMEQQQyxK4sHxmBGV+ZBEZqOcmUj+MLv/JmC+FxWkWJM0x0x7w3NqL09necWb3O42tpIVPQqYd8xipHQALfMuUhOfCgAiEA/////v///////////////3ID32shxgUrU7v0CTnVQSMCAQGhRANCAAR35M3JlAf16Omwj03nXAsmgI3kW+ZzkiVvxQmlNpJ94mDyDyrpYrvcyj1pjvQJNMoU/s5Do2i30mbzD/BlZNPx"
	//jsonData, err := json.Marshal(req)
	reqSm2 := &models.YktSm2aEncryptoReq{
		Key:     dataSecret,
		Content: jsonData,
	}
	sm2, err := helper.YktSm2Encrypto(reqSm2)

	//fmt.Println("第一次sm2加密:", sm2)
	//fmt.Println("第一次sm2加密:", err)
	YktPayReq := &models.YktPayReq{
		Appid:  appid,
		Aaz001: strconv.FormatInt(time.Now().UnixMilli(), 10),
		Data:   sm2,
	}
	jsonData1, err := json.Marshal(YktPayReq)

	uri, err := url.Parse("https://cdsmk.cdrsigc.com/engine/rest/" + code)
	//uri, err := url.Parse("http://110.185.163.36:8003/engine/rest/" + code)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println("string(jsonData1)===", string(jsonData1))
	timeStr := strconv.FormatInt(time.Now().UnixMilli(), 10)
	request_id := "cdgw" + strconv.FormatInt(time.Now().UnixMicro(), 10)
	//request_id := "8a7eaf87f92747b193b4"
	format := "json"
	access_key := "CDSGGWSLCYLZX"
	version := "1.0"
	biz_content := string(jsonData1)
	signStr := "access_key=" + access_key + "&" + "biz_content=" + biz_content + "&" + "format=" + format + "&" + "request_id=" + request_id + "&" + "timestamp=" + timeStr + "&" + "version=" + version
	priv := "MIICSwIBADCB7AYHKoZIzj0CATCB4AIBATAsBgcqhkjOPQEBAiEA/////v////////////////////8AAAAA//////////8wRAQg/////v////////////////////8AAAAA//////////wEICjp+p6dn140TVqeS89lCafzl4n1FauPkt28vUFNlA6TBEEEMsSuLB8ZgRlfmQRGajnJlI/jC7/yZgvhcVpFiTNMdMe8Nzai9PZ3nFm9zuNraSFT0KmHfMYqR0AC3zLlITnwoAIhAP////7///////////////9yA99rIcYFK1O79Ak51UEjAgEBBIIBVTCCAVECAQEEIN0M9dWs4aw27WNBeTOcLGzx1mbyYaOwEyeu0j1lL5sooIHjMIHgAgEBMCwGByqGSM49AQECIQD////+/////////////////////wAAAAD//////////zBEBCD////+/////////////////////wAAAAD//////////AQgKOn6np2fXjRNWp5Lz2UJp/OXifUVq4+S3by9QU2UDpMEQQQyxK4sHxmBGV+ZBEZqOcmUj+MLv/JmC+FxWkWJM0x0x7w3NqL09necWb3O42tpIVPQqYd8xipHQALfMuUhOfCgAiEA/////v///////////////3ID32shxgUrU7v0CTnVQSMCAQGhRANCAATcw2tmG9eKfHTgdS8/loK20JkM9gj54MA/TuHosGI5v6DQmUb6kadNVX0eUK34H8TfwzO03zHGUCBqyPL9s0R3"
	reqSm2A := &models.YktSm2EncryptoReq{
		Key:     string(priv),
		Content: signStr,
	}
	sign, err := helper.YktSignEncrypto(reqSm2A)
	if err != nil {
		fmt.Println(err)
	}
	//fmt.Println("第2次sm2加密:", sign)

	// 构建查询参数。
	data := url.Values{
		"access_key":  {access_key},
		"biz_content": {biz_content},
		"format":      {format},
		"request_id":  {request_id},
		"timestamp":   {timeStr},
		"version":     {version},
		"sign":        {sign},
	}
	//fmt.Println("data=========================", data)
	// 将查询参数转换为字节切片，并设置为请求体。
	reqBody := bytes.NewBufferString(data.Encode())

	//创建HTTP请求。
	req1, err := http.NewRequest("POST", uri.String(), reqBody)
	if err != nil {
		log.Fatal(err)
	}

	// 设置请求头，指定内容类型和长度。
	req1.Header.Set("Content-Type", "application/x-www-form-urlencoded")

	// 发送请求
	client := &http.Client{}
	resp, err := client.Do(req1)
	if err != nil {
		log.Fatal(err)
		return nil, err
	}
	defer resp.Body.Close()

	// 读取并打印响应体
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		log.Fatal(err)
	}
	return body, nil
}

// Query
//
//	@Description: 下单
//	@receiver ds
//	@param req
//	@return []models.YktModel
//	@return int64
//	@return error
func (ds *YktService) PayOp(code string, req *models.PrescriptionModel) (*models.YktPayFinalPayUrlResp, error) {
	reqPre := &models.Req4905Params{
		PatientId: req.PatientId,
		OrderNo:   req.OrderNo,
		OrderSum:  req.OrderSum,
	}
	data, err := (&HisService{}).PreBillCharge(reqPre)
	if data.ResultCode != "0" {
		return nil, errors.New("预结算失败，请联系工作人员")
	}

	// 预结算成功，唤起支付,更新订单号

	rand.Seed(time.Now().UnixNano())
	t := rand.Intn(10000)
	ts := strconv.FormatInt(time.Now().UnixMicro(), 10)
	orderSn := "CDGWYKT" + ts + strconv.Itoa(t)
	//fee, err := strconv.ParseFloat(req.OrderSum, 10)

	pat, has, err := (&models.CardModel{}).GetPatientBySourceId(req.PatientId)
	if !has {
		return nil, fmt.Errorf("用户信息不存在，请先建卡")
	}
	MchOrderId := "CDGWYKT" + strconv.Itoa(t) + req.PatientId

	//order, has, err := (&models.RegisterModel{}).FindByTransactionId(reqPay.TransactionId)
	//if !has {
	//	return nil, errors.New("订单不存在")
	//}
	////// 查看订单是否超时
	//current := time.Now().Format("2006-01-02 15:04:05")
	//currentT, err := time.Parse("2006-01-02 15:04:05", current)
	//if err != nil {
	//
	//}
	//regTime, _ := time.Parse("2006-01-02 15:04:05", order.CreatedAt.String())
	//if (currentT.Unix() - regTime.Unix()) > 610 {
	//	return nil, errors.New("订单已超时，请重新挂号")
	//}
	//
	//if order.Status != "locked" || order.PayStatus != "" {
	//	return nil, errors.New("订单状态错误")
	//}
	middlewares.Logger.Println("req.OrderSum===================", req.OrderSum)
	fee, err := strconv.ParseFloat(req.OrderSum, 64)

	middlewares.Logger.Println("feee===================", fee)
	ff := fee * 100
	//fee, err := strconv.ParseFloat(req.OrderSum, 10)
	middlewares.Logger.Println("feee===================", ff)
	if err != nil {
		return nil, errors.New("订单金额转换错误2")
	}
	reqYkt := &models.YktPayReqModel{
		IdNameOrder:     pat.RealName,
		IdNumberOrder:   pat.IdNo,
		IdTypeOrder:     "01",
		MchOrderId:      MchOrderId,
		NotifyUrl:       "",
		OrderAmount:     ff,
		OrderCreateTime: time.Now().Format("2006-01-02 15:04:05"),
		OrderDesc:       "门诊支付",
		OrderTitle:      "门诊支付",
		OrderType:       "10001",
		PayType:         "1",
		WayCode:         "SBK",
	}
	middlewares.Logger.Println("一卡通支付 入参================", reqYkt)

	jsonData, err := json.Marshal(reqYkt)
	middlewares.Logger.Println("一卡通支付 入参================", string(jsonData))
	body, err := ds.invoke(string(jsonData), code)
	if err != nil {
		return nil, err
	}
	resps := &models.YktRespModel{}
	err = json.Unmarshal(body, resps)
	middlewares.Logger.Println("一卡通支付 出参1================", string(body))
	bizData := resps.BizData
	reqSm4De := &models.YktSm4DecryptoReq{
		Key:            constant.YKTDataSecret,
		EncryptContent: bizData.Data,
	}
	decryptData, err := helper.YktSm2Decrypto(reqSm4De)
	yktPayDeResp := &models.YktPayFinalResp{}
	err = json.Unmarshal([]byte(decryptData), yktPayDeResp)
	middlewares.Logger.Println("一卡通支付 出参2================", yktPayDeResp)
	yktPayFinalPayUrlResp := &models.YktPayFinalPayUrlResp{}
	err = json.Unmarshal([]byte(yktPayDeResp.PayUrl), yktPayFinalPayUrlResp)
	middlewares.Logger.Println("一卡通支付 出参3================", yktPayFinalPayUrlResp)
	// 入库
	reqOrderIn := &models.YktOrdersModel{
		IdNameOrder:   pat.RealName,
		PatientId:     req.PatientId,
		MchOrderId:    MchOrderId,
		TransactionId: "",
		OrderAmount:   ff,
		//IdNumberOrder: reqPay.IdNumberOrder,
		PayOrderId: yktPayDeResp.PayOrderId,
		PayNo:      yktPayFinalPayUrlResp.ExtraData.PayNo,
	}
	_, err = reqOrderIn.Insert()

	//reqPaying := &models.RegisterModel{
	//	OrderSn:       MchOrderId,
	//	PayStatus:     "paying",
	//	TransactionId: reqPay.TransactionId,
	//	PayWay:        "ykt",
	//}
	//err = (&RegistrationService{}).ChangeRegOrderPaying(reqPaying)
	req.Status = "prepay"
	req.PayStatus = "paying"
	req.InvoiceNo = data.InvoiceList[0].InvoiceNo
	req.InvoiceList = data.InvoiceList
	req.OrderSn = orderSn

	err = req.Create()
	if err != nil {
		middlewares.Logger.Println("ChangeRegOrderPaying - 错误", err)
	}

	// 记录预结算入库
	pre, has, err := (&models.PrescriptionModel{}).FindPreByOrderNo(req.OrderNo)
	opm := &models.OpPreModel{
		OrderNo:     req.OrderNo,
		PatientId:   req.PatientId,
		Status:      "charge",
		InvoiceNo:   data.InvoiceList[0].InvoiceNo,
		InvoiceList: data.InvoiceList,
		ItemList:    req.ItemList,
		OrderSn:     orderSn,
	}
	if !has {
		(&models.PrescriptionModel{}).CreatePre(opm)
	}
	if has && pre.Status != "charge" {
		(&models.PrescriptionModel{}).CreatePre(opm)
	}

	if has && pre.Status == "charge" {
		(&models.PrescriptionModel{}).UpdatePre(opm)
	}

	// 该变订单状态
	// 下单成功，开始轮训订单查询接口
	if yktPayFinalPayUrlResp.ExtraData.PayNo != "" {
		var timer *time.Timer
		go func() {
			i := 0
			for {
				if i > 60 {
					timer.Stop()
					break
				}
				reqYkt := &models.YktQueryOrderReqModel{
					MchOrderId: yktPayDeResp.MchOrderId,
					PayOrderId: yktPayDeResp.PayOrderId,
				}
				jsonData1, _ := json.Marshal(reqYkt)
				respYktPay, err := ds.QueryOrder(string(jsonData1), "88800100001")
				if err != nil {
					fmt.Println("QueryOrder===========", err)
				}
				// 如果查询到，就确认支付
				if err == nil && respYktPay.PayStatus == "2" {

					local, _ := time.LoadLocation("Asia/Shanghai")
					date := time.Now().In(local).Format("2006-01-02")
					t := time.Now().In(local).Format("15:04:05")
					ConfirmRegReq := &models.Req4906Params{
						PatientId:    req.PatientId,
						CardNo:       "",
						OrderNo:      req.OrderNo,
						InvoiceNoStr: data.InvoiceList[0].InvoiceNo,
						PayAmt:       req.OrderSum,
						PlatformNo:   yktPayDeResp.MchOrderId,
						OutPayNo:     yktPayDeResp.PayOrderId,
						PayDate:      date,
						PayTime:      t,
						UpdatedBy:    "ykt_active",
						OrderSn:      yktPayDeResp.MchOrderId,
						PayModeCode:  "WXYKTZF",
					}
					middlewares.Logger.Println("ykt Register - 入参1================", ConfirmRegReq)
					jsonData, err := json.Marshal(ConfirmRegReq)
					middlewares.Logger.Println("ykt Register - 入参2================", string(jsonData))

					ree, err := (&OutPatientService{}).CompleteCharge(ConfirmRegReq)
					if err != nil {
						middlewares.Logger.Println("ykt Register - 错误", err)
					}
					middlewares.Logger.Println("ykt Register - 错误", ree)
					if ree.ResultCode == "0" {
						timer.Stop()
					}

				}
				i++
				timer = time.NewTimer(4 * time.Second)
				<-timer.C
			}
		}()

	}
	return yktPayFinalPayUrlResp, err
}
